//go:build windows
// +build windows

package config

import (
	"fmt"
	"syscall"
	"unsafe"
)

// Windows API常量
const (
	CRED_TYPE_GENERIC          = 1
	CRED_PERSIST_LOCAL_MACHINE = 2
)

// Windows CREDENTIAL结构体
type CREDENTIAL struct {
	Flags              uint32
	Type               uint32
	TargetName         *uint16
	Comment            *uint16
	LastWritten        uint64
	CredentialBlobSize uint32
	CredentialBlob     *byte
	Persist            uint32
	AttributeCount     uint32
	Attributes         uintptr
	TargetAlias        *uint16
	UserName           *uint16
}

// Windows Credential Manager相关变量
var (
	modAdvapi32    = syscall.NewLazyDLL("advapi32.dll")
	procCredWrite  = modAdvapi32.NewProc("CredWriteW")
	procCredRead   = modAdvapi32.NewProc("CredReadW")
	procCredDelete = modAdvapi32.NewProc("CredDeleteW")
	procCredFree   = modAdvapi32.NewProc("CredFree")
	credTargetName = "PasswordResetMasterKey"
)

// initialize Windows系统初始化
func (skm *SecureKeyManager) initialize() error {
	// 首先尝试从Windows Credential Manager读取
	key, err := skm.getMasterKey()
	if err == nil {
		skm.masterKey = key
		return nil
	}

	// 如果不存在，生成新的主密钥
	key, err = GenerateEncryptionKey()
	if err != nil {
		return fmt.Errorf("生成主密钥失败: %v", err)
	}

	// 保存到Windows Credential Manager
	if err := skm.saveMasterKey(key); err != nil {
		return fmt.Errorf("保存主密钥失败: %v", err)
	}

	skm.masterKey = key
	return nil
}

// getMasterKey 从Windows Credential Manager获取主密钥
func (skm *SecureKeyManager) getMasterKey() ([]byte, error) {
	var pcred *CREDENTIAL
	ret, _, err := procCredRead.Call(
		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(credTargetName))),
		CRED_TYPE_GENERIC,
		0,
		uintptr(unsafe.Pointer(&pcred)),
	)

	if ret == 0 {
		return nil, fmt.Errorf("读取凭证失败: %v", err)
	}
	defer procCredFree.Call(uintptr(unsafe.Pointer(pcred)))

	// 复制密钥数据
	key := make([]byte, pcred.CredentialBlobSize)
	copy(key, (*[1 << 20]byte)(unsafe.Pointer(pcred.CredentialBlob))[:pcred.CredentialBlobSize])

	return key, nil
}

// saveMasterKey 保存主密钥到Windows Credential Manager
func (skm *SecureKeyManager) saveMasterKey(key []byte) error {
	cred := &CREDENTIAL{
		Type:               CRED_TYPE_GENERIC,
		TargetName:         syscall.StringToUTF16Ptr(credTargetName),
		CredentialBlobSize: uint32(len(key)),
		CredentialBlob:     &key[0],
		Persist:            CRED_PERSIST_LOCAL_MACHINE,
	}

	ret, _, err := procCredWrite.Call(uintptr(unsafe.Pointer(cred)), 0)
	if ret == 0 {
		return fmt.Errorf("写入凭证失败: %v", err)
	}

	return nil
}